package com.example.mykotlin.base.config

import com.example.mykotlin.base.util.GetBean
import com.example.mykotlin.base.util.RedissonUtil
import com.github.yitter.contract.IdGeneratorOptions
import com.github.yitter.idgen.YitIdHelper
import org.slf4j.LoggerFactory
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.core.annotation.Order
import org.springframework.core.env.Environment
import org.springframework.stereotype.Component

@Component
@Order(0)
class YitterIdInitConfig(
    private val environment: Environment,
) : ApplicationRunner {

    override fun run(args: ApplicationArguments?) {
        // 获取mac地址
        val name = environment.getProperty("spring.application.name") ?: "poiuy"
        val lockKey = "$CACHE_ID_GENERATOR:$name"
        try {
            // 分布式锁等待120秒，执行时长最大120秒
            val locked: Boolean = RedissonUtil.tryLock(lockKey, 120, 120)
            if (!locked) {
                workId = (Math.random() * 10000).toInt() + 10000
                return
            }
            val idSetName = "$ID_GENERATOR_KEY:$name"
            val opsForSet = GetBean.redisTemplate().opsForSet()
            val set = opsForSet.members(idSetName)
            if (set.isNullOrEmpty()) {
                opsForSet.add(idSetName, workId)
            } else {
                val iterator = set.iterator()
                var index = 1
                while (iterator.hasNext() && index == iterator.next()) {
                    index++
                }
                workId = index
                opsForSet.add(idSetName, workId)
            }
        } finally {
            val options = IdGeneratorOptions(workId.toShort())
            options.SeqBitLength = 10
            YitIdHelper.setIdGenerator(options)
            RedissonUtil.unlock(lockKey)
            log.info("服务分配到WorkId：{}", workId)
        }
    }

    companion object {

        private val log = LoggerFactory.getLogger(YitterIdInitConfig::class.java)

        /**
         * 分布式锁Key
         */
        private const val CACHE_ID_GENERATOR = "LOCK_ID_GENERATOR"

        /**
         * 已分配的机器号Key
         */
        const val ID_GENERATOR_KEY = "ID_GENERATOR_KEY"

        private var workId: Int = 1

        fun getWorkId() = workId

    }

}